#include "event_loop.hpp"

using namespace event_framework;

bool EventLoop::Init()
{
    if (!awakener.Init()) return false;
    if (!timerQue.Init()) return false;
    if (!poller.Init()) return false;
    return true;
}

void EventLoop::Loopback(EventLoop& other, Command&& request, Callback&& callback)
{
    ASSERT(request);
    ASSERT(callback);
    auto transfunc = [&other, request, callback] ()
    {
        request();
        other.Accept(
            [callback]() { callback(); }
        );
    };
    Accept(transfunc);
}
void EventLoop::Loopback(EventLoop& other, RetCommand&& request, CallbackRet&& callback)
{
    ASSERT(request);
    ASSERT(callback);
    auto transfunc = [&other, request, callback] ()
    {
        auto ret = request();
        other.Accept(
            [callback, ret]() { callback(ret); }
        );
    };
    Accept(transfunc);
}

void EventLoop::Loop()
{
    while (quit)
    {
        // 1. process epoll reactor
        Poll();
        // 2. process command event
        HandleCommands();
    }
}

void EventLoop::Poll()
{
    // process epoll event, includes socketfd, eventfd and timerfd
    ChannelList clist;
    poller.Poll(clist);
    for (const auto& ch : clist)
    {
        ASSERT(ch != nullptr);
        ch->HandleEvents();
    }
}
void EventLoop::HandleCommands()
{
    std::list<Command> localQue;
    cmdQue.Take(localQue);
    for (auto& cmd : localQue)
    {
        ASSERT(cmd);
        cmd();
    }
}